// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package api

import (
	"apiote.xyz/p/szczanieckiej/traffic"
	"fmt"
)

func MakeLineResponse(line traffic.Line, context traffic.Context, t *traffic.Traffic, accept map[uint]struct{}) (LineResponse, error) {
	if _, ok := accept[0]; ok {
		response := LineResponseDev{
			Line: LineV3{},
		}
		line, err := makeLineV3(line, context, t)
		response.Line = line
		return response, err
	}
	if _, ok := accept[3]; ok {
		response := LineResponseV3{
			Line: LineV3{},
		}
		line, err := makeLineV3(line, context, t)
		response.Line = line
		return response, err
	}
	if _, ok := accept[2]; ok {
		response := LineResponseV2{
			Line: LineV2{},
		}
		line, err := makeLineV2(line, context, t)
		response.Line = line
		return response, err
	}
	if _, ok := accept[1]; ok {
		response := LineResponseV1{
			Line: LineV1{},
		}
		line, err := makeLineV1(line, context, t)
		response.Line = line
		return response, err
	}

	return LineResponseDev{}, AcceptError
}

func makeLineV3(line traffic.Line, context traffic.Context, t *traffic.Traffic) (LineV3, error) {
	l := convertTrafficLineV3(line, context.FeedID)
	lG, err := convertTrafficLineGraphsV1(line, context, t)
	if err != nil {
		return LineV3{}, fmt.Errorf("while converting graph: %w", err)
	}
	l.Graphs = lG
	return l, nil
}

func makeLineV2(line traffic.Line, context traffic.Context, t *traffic.Traffic) (LineV2, error) {
	l := convertTrafficLineV2(line, context.FeedID)
	lG, err := convertTrafficLineGraphsV1(line, context, t)
	if err != nil {
		return LineV2{}, fmt.Errorf("while converting graph: %w", err)
	}
	l.Graphs = lG
	return l, nil
}

func makeLineV1(line traffic.Line, context traffic.Context, t *traffic.Traffic) (LineV1, error) {
	l := convertTrafficLine(line, context.FeedID)
	lG, err := convertTrafficLineGraphsV1(line, context, t)
	if err != nil {
		return LineV1{}, fmt.Errorf("while converting graph: %w", err)
	}
	l.Graphs = lG
	return l, nil
}

func convertTrafficLineV3(line traffic.Line, feedID string) LineV3 {
	l := LineV3{
		Id:        line.Id,
		Name:      line.Name,
		Colour:    fromColor(line.Colour),
		Kind:      makeLineTypeV3(line),
		FeedID:    feedID,
		Headsigns: line.Headsigns,
	}

	return l
}

func convertTrafficLineV2(line traffic.Line, feedID string) LineV2 {
	l := LineV2{
		Name:      line.Name,
		Colour:    fromColor(line.Colour),
		Kind:      makeLineTypeV3(line),
		FeedID:    feedID,
		Headsigns: line.Headsigns,
	}

	return l
}

func convertTrafficLine(line traffic.Line, feedID string) LineV1 {
	l := LineV1{
		Name:      line.Name,
		Colour:    fromColor(line.Colour),
		Kind:      makeLineTypeV2(line),
		FeedID:    feedID,
		Headsigns: line.Headsigns,
	}

	return l
}

func convertTrafficLineGraphsV1(trafficLine traffic.Line, context traffic.Context, t *traffic.Traffic) ([]LineGraphV1, error) {
	lineGraphs := []LineGraphV1{}
	for _, graph := range trafficLine.Graphs {
		if len(graph.StopCodes) != 0 {
			lineGraph := LineGraphV1{
				Stops:     make([]StopStubV1, len(graph.StopCodes)),
				NextNodes: graph.NextNodes,
			}
			for i, code := range graph.StopCodes {
				stopStub, err := traffic.GetStopStub(code, trafficLine.Id, context, t)
				if err != nil {
					return lineGraphs, fmt.Errorf("while getting stopStub for %s: %w", code, err)
				}
				lineGraph.Stops[i] = convertTrafficStopStub(stopStub)
			}
			lineGraphs = append(lineGraphs, lineGraph)
		}
	}

	return lineGraphs, nil
}
